package com.lam.common.utils.http;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.Args;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lam.common.utils.CollectionUtil;
import com.lam.common.utils.StringUtils;

public class HttpFactoryUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(HttpFactoryUtil.class);
	
	private static List<String> verifyHostnameList = new ArrayList<>();
	
	static {
//		VERIFY_HOST_NAME_ARRAY.add("")
	}
	
	public static List<String> verifyHostnameAdd(String ... arr){
		if(CollectionUtil.isEmpty(verifyHostnameList)){
			return verifyHostnameList;
		}
		for (String s : arr) {
			verifyHostnameList.add(s);
		}
		return verifyHostnameList;
	}
	
	public static SSLConnectionSocketFactory getDefaultSocketFactory(){
		return SSLConnectionSocketFactory.getSocketFactory();
	}
	
	public static SSLConnectionSocketFactory getPKCS12(String privateCerPath, String privateCerPass, String serverCerPath, String serverCerPass){
		
		try (InputStream privateCerIs = new FileInputStream(new File(privateCerPath))){
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			keyStore.load(privateCerIs, privateCerPass.toCharArray());
			SSLContext sslcontext = SSLContexts.custom()
					//加载服务端提供的truststore(如果服务器提供truststore的话就不用忽略对服务器端证书的校验了)
					.loadTrustMaterial(new File(serverCerPath), serverCerPass.toCharArray(), new TrustSelfSignedStrategy())
			        .loadKeyMaterial(keyStore, privateCerPass.toCharArray()).build();
			return new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
			        getInsecureHostnameVerifier());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return getDefaultSocketFactory();
		}
	}
	
	public static HostnameVerifier getInsecureHostnameVerifier(){
		
		final List<String> list = verifyHostnameList;
		return (hostname, session)->{
             if (StringUtils.isEmpty(hostname)) {
                 return false;
             }
             return list.contains(hostname);
	     };
	}
	
	public static HostnameVerifier getTrustAnyHostnameVerifier() {
		return (hostname, session)->true;
	}
	
	public static ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy(){
		return connectionKeepAliveStrategy;
	}
	
	private static ConnectionKeepAliveStrategy connectionKeepAliveStrategy = (response, context)->{
		Args.notNull(response, "HTTP response");
		final HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
		while (it.hasNext()) {
			final HeaderElement he = it.nextElement();
			final String param = he.getName();
			final String value = he.getValue();
			if (value != null && param.equalsIgnoreCase("timeout")) {
				try {
					return Long.parseLong(value) * 1000;
				} catch (final NumberFormatException ignore) {}
			}
		}
		return 1;
	};
	
}

class TrustAnyTrustManager implements X509TrustManager {
	@Override
	public void checkClientTrusted(X509Certificate[] chain, String authType) {
	}

	@Override
	public void checkServerTrusted(X509Certificate[] chain, String authType) {
	}

	@Override
	public X509Certificate[] getAcceptedIssuers() {
		return new X509Certificate[] {};
	}
}